home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * Fchart -- flblarr.c
- *
- * Copyright (C) 1990 Piotr Filip Sawicki
- *
- * Permission to use, copy, and distribute this software and its
- * documentation for any purpose with or without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and
- * that both that copyright notice and this permission notice appear
- * in supporting documentation.
- *
- * Permission to modify the software is granted, but not the right to
- * distribute the modified code. Modifications are to be distributed
- * as patches to released version.
- *
- * Please e-mail any useful additions to fs@uwasa.fi so they may be
- * included in later releases.
- *
- * This file should be edited with 4-column tabs! (:set ts=4 sw=4 in vi)
- */
-
- #include <stdio.h>
- #include <math.h>
- #include "plot.h"
- #include "fchart.h"
-
- struct label_def *first_label = NULL;
- struct linearrow_def *first_arrow = NULL;
-
- extern char *strcpy(),*strcat();
- extern int strlen();
-
- /* input data, parsing variables */
- extern struct lexical_unit token[];
- extern char input_line[];
- extern int num_tokens, c_token;
-
- extern double real();
-
- /******** Local functions ********/
- static int assign_label_tag();
- static int assign_arrow_tag();
- static void delete_label();
- static void delete_arrow();
-
- /* not static: used by fcmd.c */
- void show_labels(), show_arrow();
- void set_label();
- void set_nolabel();
- void set_arrow();
- void set_noarrow();
-
- /* process a 'set label' command */
- /* set label {tag} {label_text} {at {page|picture} x,y} {pos} {height h} {width w} */
- void
- set_label()
- {
- struct label_def *this_label = NULL;
- struct label_def *new_label = NULL;
- struct label_def *prev_label = NULL;
- double x, y, h, w, a;
- char text[MAX_LINE_LEN+1];
- enum JUSTIFY just = LEFT;
- enum LAB_ROT rot;
- int tag;
- BOOLEAN set_text, set_position, set_just=FALSE, set_h, set_w, set_r;
- BOOLEAN page_label;
-
- /* get tag */
- if (!END_OF_COMMAND && isnumber(c_token)) {
- tag = (int)real(c_token);
- if (tag == 0)
- int_error("tag must be > zero", c_token);
- c_token++;
- } else
- tag = assign_label_tag(); /* default next tag */
-
- /* get text */
- if (!END_OF_COMMAND && isstring(c_token)) {
- quote_str(text, c_token);
- c_token++;
- set_text = TRUE;
- } else {
- text[0] = '\0'; /* default no text */
- set_text = FALSE;
- }
-
- /* get justification -- why not here ? */
- if (!END_OF_COMMAND) {
- if (almost_equals(c_token,"l$eft")) {
- just = LEFT;
- set_just = TRUE;
- c_token++;
- }
- else if (almost_equals(c_token,"c$entre")
- || almost_equals(c_token,"c$enter")) {
- just = CENTRE;
- set_just = TRUE;
- c_token++;
- }
- else if (almost_equals(c_token,"ri$ght")) {
- just = RIGHT;
- set_just = TRUE;
- c_token++;
- }
- }
-
- /* get position */
- if (!END_OF_COMMAND && equals(c_token, "at")) {
- c_token++;
- if (END_OF_COMMAND)
- int_error("coordinates expected", c_token);
- if (almost_equals(c_token, "pa$ge")) {
- c_token++;
- page_label = TRUE;
- }
- else if (almost_equals(c_token, "pi$cture")) {
- c_token++;
- page_label = FALSE;
- }
- else if (!isnumber(c_token))
- int_error("'page' or 'picture' expected", c_token);
- else
- page_label = FALSE;
- x = real(c_token++);
- if (!equals(c_token,","))
- int_error("',' expected", c_token);
- else
- c_token++;
- y = real(c_token++);
- set_position = TRUE;
- } else {
- x = y = 0; /* default at origin */
- page_label = FALSE;
- set_position = FALSE;
- }
-
- /* get justification */
- if (!END_OF_COMMAND) {
- if (almost_equals(c_token,"l$eft")) {
- if (set_just)
- int_error("only one justification is allowed", c_token);
- just = LEFT;
- set_just = TRUE;
- c_token++;
- }
- else if (almost_equals(c_token,"c$entre")
- || almost_equals(c_token,"c$enter")) {
- if (set_just)
- int_error("only one justification is allowed", c_token);
- just = CENTRE;
- set_just = TRUE;
- c_token++;
- }
- else if (almost_equals(c_token,"ri$ght")) {
- if (set_just)
- int_error("only one justification is allowed", c_token);
- just = RIGHT;
- set_just = TRUE;
- c_token++;
- }
- }
-
- /* get height */
- if (!END_OF_COMMAND && almost_equals(c_token, "he$ight")) {
- c_token++;
- h = real(c_token++);
- set_h = TRUE;
- }
- else {
- h = 0.0;
- set_h = FALSE;
- }
-
- /* get width */
- if (!END_OF_COMMAND && almost_equals(c_token, "wi$dth")) {
- c_token++;
- w = real(c_token++);
- set_w = TRUE;
- }
- else {
- w = 0.0;
- set_w = FALSE;
- }
-
- /* get angle */
- if (!END_OF_COMMAND && almost_equals(c_token, "ro$tation")) {
- int sign = 1;
- c_token++;
- if (equals(c_token, "-")) {
- c_token++;
- sign = -1;
- }
- a = (double)sign * real(c_token++);
- rot = L_RANDOM;
- set_r = TRUE;
- }
- else if (!END_OF_COMMAND) {
- if (almost_equals(c_token, "di$rection")) {
- c_token++;
- set_r = TRUE; /* empty direction defaults to normal */
- }
- else
- set_r = FALSE;
- if (!END_OF_COMMAND && (almost_equals(c_token, "n$orth") ||
- almost_equals(c_token, "v$ertical") || almost_equals(c_token, "u$p"))) {
- c_token++;
- rot = L_BOTTOM;
- set_r = TRUE;
- }
- else if (!END_OF_COMMAND && (almost_equals(c_token, "s$outh") ||
- almost_equals(c_token, "do$wn"))) {
- c_token++;
- rot = L_TOP;
- set_r = TRUE;
- }
- else if (!END_OF_COMMAND && (almost_equals(c_token, "we$st") ||
- almost_equals(c_token, "l$eft"))) {
- c_token++;
- rot = L_UPSIDE;
- set_r = TRUE;
- }
- else if (!END_OF_COMMAND && (almost_equals(c_token, "ho$rizontal") ||
- almost_equals(c_token, "e$ast") || almost_equals(c_token, "ri$ght"))) {
- c_token++;
- rot = L_NORMAL;
- set_r = TRUE;
- }
- else {
- rot = L_NORMAL;
- }
- }
- else {
- rot = L_NORMAL;
- set_r = FALSE;
- }
-
- if (!END_OF_COMMAND)
- int_error("extraneous or out-of-order arguments in set label", c_token);
-
- /* OK! add label */
- if (first_label != NULL) { /* skip to last label */
- for (this_label = first_label; this_label != NULL ;
- prev_label = this_label, this_label = this_label->next)
- /* is this the label we want? */
- if (tag <= this_label->tag)
- break;
- }
- if (this_label != NULL && tag == this_label->tag) {
- /* changing the label */
- if (set_position) {
- this_label->x = x;
- this_label->y = y;
- this_label->paged = page_label;
- }
- if (set_text)
- (void) strcpy(this_label->text, text);
- if (set_just)
- this_label->pos = just;
- if (set_h)
- this_label->h = h;
- if (set_w)
- this_label->w = w;
- if (set_r) {
- this_label->rot = rot;
- this_label->a = a;
- }
- } else {
- /* adding the label */
- new_label = (struct label_def *)
- alloc ( (unsigned int) sizeof(struct label_def), "label");
- if (prev_label != NULL)
- prev_label->next = new_label; /* add it to end of list */
- else
- first_label = new_label; /* make it start of list */
- new_label->tag = tag;
- new_label->next = this_label;
- new_label->x = x;
- new_label->y = y;
- (void) strcpy(new_label->text, text);
- new_label->pos = just;
- new_label->h = h;
- new_label->w = w;
- new_label->rot = rot;
- new_label->a = a;
- new_label->paged = page_label;
- }
- }
-
- /* process 'set nolabel' command */
- /* set nolabel {tag} */
- void
- set_nolabel()
- {
- struct label_def *this_label;
- struct label_def *prev_label;
- int tag;
-
- if (END_OF_COMMAND) { /* delete all labels */
- while (first_label != NULL)
- delete_label((struct label_def *)NULL, first_label);
- }
- else {
- tag = (int)real(c_token++);
- if (!END_OF_COMMAND)
- int_error("extraneous arguments to set nolabel", c_token);
- for (this_label = first_label, prev_label = NULL;
- this_label != NULL;
- prev_label = this_label, this_label = this_label->next) {
- if (this_label->tag == tag) {
- delete_label(prev_label, this_label);
- return; /* exit, our job is done */
- }
- }
- int_error("label not found", c_token);
- }
- }
-
- /* assign a new label tag */
- /* labels are kept sorted by tag number, so this is easy */
- static int /* the lowest unassigned tag number */
- assign_label_tag()
- {
- struct label_def *this_label;
- int last = 0; /* previous tag value */
-
- for (this_label = first_label; this_label != NULL;
- this_label = this_label->next)
- if (this_label->tag == last+1)
- last++;
- else
- break;
-
- return (last+1);
- }
-
- /* delete label from linked list started by first_label.
- * called with pointers to the previous label (prev) and the
- * label to delete (this).
- * If there is no previous label (the label to delete is
- * first_label) then call with prev = NULL.
- */
- static void
- delete_label(prev,this)
- struct label_def *prev, *this;
- {
- if (this!=NULL) { /* there really is something to delete */
- if (prev!=NULL) /* there is a previous label */
- prev->next = this->next;
- else /* this = first_label so change first_label */
- first_label = this->next;
- free((char *)this);
- }
- }
-
-
- /* process a 'set arrow' and 'set line' command */
- /* set arrow|line {tag} {from { {page|picture} x,y} {to {page|picture} x,y} */
- void
- set_arrow(arrow)
- BOOLEAN arrow;
- {
- struct linearrow_def *this_arrow = NULL;
- struct linearrow_def *new_arrow = NULL;
- struct linearrow_def *prev_arrow = NULL;
- double sx, sy;
- double ex, ey;
- int tag;
- BOOLEAN set_start, set_end;
- BOOLEAN sp, ep;
-
- /* get tag */
- if (!END_OF_COMMAND && isnumber(c_token)) {
- tag = (int)real(c_token++);
- if (tag == 0)
- int_error("tag must be > zero", c_token);
- } else
- tag = assign_arrow_tag(); /* default next tag */
-
- /* get start position */
- if (!END_OF_COMMAND && almost_equals(c_token, "f$rom")) {
- c_token++;
- if (END_OF_COMMAND)
- int_error("start coordinates expected", c_token);
- else if (almost_equals(c_token, "pa$ge")) {
- c_token++;
- sp = TRUE;
- }
- else if (almost_equals(c_token, "pi$cture")) {
- c_token++;
- sp = FALSE;
- }
- else
- sp = FALSE;
-
- sx = real(c_token++);
- if (!equals(c_token,","))
- int_error("',' expected",c_token);
- c_token++;
- sy = real(c_token++);
- set_start = TRUE;
- } else {
- sx = sy = 0; /* default at origin */
- sp = FALSE;
- set_start = FALSE;
- }
-
- /* get end position */
- if (!END_OF_COMMAND && almost_equals(c_token, "t$o")) {
- c_token++;
- if (END_OF_COMMAND)
- int_error("end coordinates expected", c_token);
- else if (almost_equals(c_token, "pa$ge")) {
- c_token++;
- ep = TRUE;
- }
- else if (almost_equals(c_token, "pi$cture")) {
- c_token++;
- ep = FALSE;
- }
- else
- ep = FALSE;
-
- ex = real(c_token++);
- if (!equals(c_token,","))
- int_error("',' expected",c_token);
- c_token++;
- ey = real(c_token++);
- set_end = TRUE;
- } else {
- ex = ey = 0; /* default at origin */
- ep = FALSE;
- set_end = FALSE;
- }
-
- /* get start position - what the heck, either order is ok */
- if (!END_OF_COMMAND && almost_equals(c_token, "f$rom")) {
- if (set_start)
- int_error("only one 'from' is allowed", c_token);
- c_token++;
- if (END_OF_COMMAND)
- int_error("start coordinates expected", c_token);
- else if (almost_equals(c_token, "pa$ge")) {
- c_token++;
- sp = TRUE;
- }
- else if (almost_equals(c_token, "pi$cture")) {
- c_token++;
- sp = FALSE;
- }
- else
- sp = FALSE;
-
- sx = real(c_token++);
- if (!equals(c_token,","))
- int_error("',' expected",c_token);
- c_token++;
- sy = real(c_token++);
- set_start = TRUE;
- }
-
- if (!END_OF_COMMAND)
- int_error("extraneous or out-of-order arguments in set arrow/line", c_token);
-
- /* OK! add arrow */
- if (first_arrow != NULL) { /* skip to last arrow */
- for (this_arrow = first_arrow; this_arrow != NULL ;
- prev_arrow = this_arrow, this_arrow = this_arrow->next)
- /* is this the arrow we want? */
- if (tag <= this_arrow->tag)
- break;
- }
- if (this_arrow != NULL && tag == this_arrow->tag) {
- /* changing the arrow */
- if (set_start) {
- this_arrow->sx = sx;
- this_arrow->sy = sy;
- this_arrow->startp = sp;
- }
- if (set_end) {
- this_arrow->ex = ex;
- this_arrow->ey = ey;
- this_arrow->endp = ep;
- }
- this_arrow->arrow = arrow;
- } else {
- /* adding the arrow */
- new_arrow = (struct linearrow_def *)
- alloc ( (unsigned int) sizeof(struct linearrow_def), "arrow");
- if (prev_arrow != NULL)
- prev_arrow->next = new_arrow; /* add it to end of list */
- else
- first_arrow = new_arrow; /* make it start of list */
- new_arrow->tag = tag;
- new_arrow->next = this_arrow;
- new_arrow->sx = sx;
- new_arrow->sy = sy;
- new_arrow->startp = sp;
- new_arrow->ex = ex;
- new_arrow->ey = ey;
- new_arrow->endp = ep;
- new_arrow->arrow = arrow;
- }
- }
-
- /* process 'set noarrow' and 'set noline' command */
- /* set noarrow {tag} */
- void
- set_noarrow()
- {
- struct linearrow_def *this_arrow;
- struct linearrow_def *prev_arrow;
- int tag;
-
- if (END_OF_COMMAND) {
- /* delete all arrows */
- while (first_arrow != NULL)
- delete_arrow((struct linearrow_def *)NULL,first_arrow);
- }
- else {
- /* get tag */
- tag = (int)real(c_token++);
- if (!END_OF_COMMAND)
- int_error("extraneous arguments to set noarrow/noline", c_token);
- for (this_arrow = first_arrow, prev_arrow = NULL;
- this_arrow != NULL;
- prev_arrow = this_arrow, this_arrow = this_arrow->next) {
- if (this_arrow->tag == tag) {
- delete_arrow(prev_arrow, this_arrow);
- return; /* exit, our job is done */
- }
- }
- int_error("arrow/line not found", c_token);
- }
- }
-
- /* assign a new arrow tag */
- /* arrows are kept sorted by tag number, so this is easy */
- static int /* the lowest unassigned tag number */
- assign_arrow_tag()
- {
- struct linearrow_def *this_arrow;
- int last = 0; /* previous tag value */
-
- for (this_arrow = first_arrow; this_arrow != NULL;
- this_arrow = this_arrow->next)
- if (this_arrow->tag == last+1)
- last++;
- else
- break;
-
- return (last+1);
- }
-
- /* delete arrow from linked list started by first_arrow.
- * called with pointers to the previous arrow (prev) and the
- * arrow to delete (this).
- * If there is no previous arrow (the arrow to delete is
- * first_arrow) then call with prev = NULL.
- */
- static void
- delete_arrow(prev,this)
- struct linearrow_def *prev, *this;
- {
- if (this!=NULL) { /* there really is something to delete */
- if (prev!=NULL) /* there is a previous arrow */
- prev->next = this->next;
- else /* this = first_arrow so change first_arrow */
- first_arrow = this->next;
- free((char *)this);
- }
- }
-
- void
- show_labels(tag, fp, save)
- int tag; /* 0 means show all */
- FILE *fp;
- BOOLEAN save;
- {
- struct label_def *this_label;
- BOOLEAN showed = FALSE;
-
- for (this_label = first_label; this_label != NULL;
- this_label = this_label->next) {
- if (tag == 0 || tag == this_label->tag) {
- showed = TRUE;
- fprintf(fp,"%slabel %d \"%s\" %s at %s %lg,%lg",
- save ? "set " : "\t",
- this_label->tag, this_label->text,
- (this_label->pos==LEFT ? "left" : (this_label->pos==RIGHT ? "right" : "centre")),
- this_label->paged ? "page" : "picture",
- this_label->x, this_label->y);
- if (this_label->h != 0.0)
- fprintf(fp, " height %lg", this_label->h);
- if (this_label->w != 0.0)
- fprintf(fp, " width %lg", this_label->w);
- switch(this_label->rot) {
- case L_NORMAL: {
- break;
- }
- case L_UPSIDE: {
- fprintf(fp, " direction left");
- break;
- }
- case L_BOTTOM: {
- fprintf(fp, " vertical");
- break;
- }
- case L_TOP: {
- fprintf(fp, " direction down");
- break;
- }
- case L_RANDOM: {
- fprintf(fp, " rotation %lg", this_label->a);
- break;
- }
- }
- fputc('\n',fp);
- }
- }
- if (tag > 0 && !showed)
- int_error("label not found", c_token);
- }
-
- void
- show_arrow(tag, fp, save)
- int tag; /* 0 means show all */
- FILE *fp;
- BOOLEAN save;
- {
- struct linearrow_def *this_arrow;
- BOOLEAN showed = FALSE;
-
- for (this_arrow = first_arrow; this_arrow != NULL;
- this_arrow = this_arrow->next) {
- if (tag == 0 || tag == this_arrow->tag) {
- showed = TRUE;
- fprintf(fp,"%s%s %d from %s %lg,%lg to %s %lg,%lg\n",
- save ? "set " : "\t",
- this_arrow->arrow ? "arrow" : "line",
- this_arrow->tag,
- this_arrow->startp ? "page" : "picture",
- this_arrow->sx, this_arrow->sy,
- this_arrow->endp ? "page" : "picture",
- this_arrow->ex, this_arrow->ey);
- }
- }
- if (tag > 0 && !showed)
- int_error("arrow not found", c_token);
- }
-
-
-
-
-
-
-
-
-
-